package com.fyzk.activity.lottery.jc.football;

import com.fyzk.activity.lottery.jc.football.guoguan.JC_GuoGuanInfor;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * 竞彩 注数计算类
 * @author mm
 *
 */
public class JZBetNumUtil {
	
	/**
	 * 自由过关计算注数
	 * @param select  选择 n串1 的n值  例如 2串1 则 select的 值 为2
	 * @param betcodes  每场比赛选择的  个数
	 * @param isDanList   单场比赛 是否被选择为胆码 的Boolean值 的集合
	 * @return 这个串 对应的注数
	 */
	public static int getZhushu(int select,List<Integer> betcodes,List<Boolean> isDanList){
		int isDanNum = getIsDanNum(isDanList);
		return getAllAmt(betcodes, select,isDanList,isDanNum);
	}
	
	/**
	 * 返回总注数竞彩自由过关投注计算注数
	 * 
	 * @param betcodes
	 * @param select
	 * @return
	 */
	public static int getAllAmt(List<Integer> betcodes, int select, List<Boolean> isDanList, int isDanNum) {
		List<int[]> list = goCombine(select, betcodes.size());
		// 返回数据对象
		int resultInt = 0;
		for (int[] result : list) {
			int itemNum = 1;
			int danNum = 0;
			for (int p : result) {
				itemNum *= betcodes.get(p);
				if (isDanNum > 0 && isDanList.get(p)) {
					danNum++;
				}
			}
			if (isDanNum == 0 || danNum == isDanNum) {
				resultInt += itemNum;
			}
		}

		return resultInt;
	}
	
	/**
	 * 多串过关计算注数
	 * @param select
	 * @return
	 */
	public static int getDuoZhushu(int teamNum,int select,List<Boolean> isDanList,List<Integer> betcodes){
		 int isDanNum = getIsDanNum(isDanList);
		return getDouZhushu(teamNum, betcodes, select,isDanList,isDanNum);
	}

	/**
	 * 返回总注数竞彩多串过关投注计算注数
	 * 
	 * @param teamNum
	 *            多串过关3*3 teamNum = 3
	 * @param select
	 *            2*1 select=2
	 * @return 将几场比赛分成几组
	 */
	public static int getDouZhushu(int teamNum, List<Integer> betcodes, int select, List<Boolean> isDanList, int isDanNum) {
		List<int[]> list = goCombine(teamNum, betcodes.size());
		List<int[]> listAll = new ArrayList<int[]>();
		for (int i = 0; i < select; i++) {
			for (int[] ints : list) {
				listAll.add(ints);
			}
		}

		int resultInt = 0;
		resultInt = getAllAmtDuo(betcodes,listAll, teamNum, isDanList, isDanNum);

		return resultInt;
	}
	
	/**
	 * 返回总注数竞彩自由过关投注计算注数
	 * 
	 * @param betcodes
	 * @param select
	 * @return
	 */
	public static int getAllAmtDuo(List<Integer> betcodes,List<int[]> list, int select, List<Boolean> isDanList, int isDanNum) {
		// 返回数据对象
		int resultInt = 0;
		for (int[] result : list) {
			int itemNum = 1;
			int danNum = 0;
			for (int p : result) {
				itemNum *= betcodes.get(p);
				if (isDanNum > 0 && isDanList.get(p)) {
					danNum++;
				}
			}
			if (isDanNum == 0 || danNum == isDanNum) {
				resultInt += itemNum;
			}
		}

		return resultInt;
	}

	/**
	 * 两分组是否相同
	 * @param result
	 * @param resultItem
	 * @return
	 */
	private static boolean isDiffResult(int[] result, int[] resultItem) {
		int diffNum = 0;
		 for(int n=0;n<result.length;n++){
			 int nNum = result[n];
			 for(int m=0;m<resultItem.length;m++){
				 int mNum = resultItem[m];
				 if(nNum==mNum){
					 diffNum++;
				 }
			 }
		 }
		 if(diffNum == result.length){
			 return true;
		 }else{
			 return false;
		 }
	}

    /**
     * 进行组合的方法
     * @param teamNum
     * @param listSize
     * @return
     */
	private static List<int[]> goCombine(int teamNum, int listSize) {
		// 初始化原始数据
		int[] a = new int[listSize];
		for (int i = 0; i < a.length; i++) {
			a[i] = i;
		}
		// 接收数据
		int[] b = new int[teamNum];

		List<int[]> list = new ArrayList<int[]>();

		// 进行组合
		combine(a, a.length, teamNum, b, teamNum, list);
		return list;
	}
	
	/**
	 * 获取设胆个数
	 * @return
	 */
	public static int getIsDanNum(List<Boolean> isDanList){
		int num = 0;
		for(int i=0;i<isDanList.size();i++){
			if(isDanList.get(i)){
				num++;
			}
		}
		return num;
	}
	/**
	 * 单关计算注数
	 * @param  betcodes
	 * @return
	 */
	public int getDanZhushu(List<Integer> betcodes){
		return getDanAAmt(betcodes);
	}
	
	/**
	 * 返回总注数竞彩自由过关投注计算注数
	 * 
	 * @param betcodes
	 * @param select
	 * @return
	 */
	public static int getAllAmt(List<Integer> betcodes, int select) {
		List<int[]> list = goCombine(select, betcodes.size());
		// 返回数据对象
		int resultInt = 0;
		for (int[] result : list) {
			int itemNum = 1;
			for (int p : result) {
				itemNum *= betcodes.get(p);
			}
			resultInt+=itemNum;
		}

		return resultInt;
	}
    /**
     * 单关投注计算注数
     * @param betcodes
     * @return
     */
	public static int getDanAAmt(List<Integer> betcodes) {
		int zhushu = 0;
		for (int i = 0; i < betcodes.size(); i++) {
			zhushu += betcodes.get(i);
		}
		return zhushu;
	}

	
	/**
	 * 组合的递归算法
	 * 
	 * @param a
	 *            原始数据
	 * @param n
	 *            原始数据个数
	 * @param m
	 *            选择数据个数
	 * @param b
	 *            存放被选择的数据
	 * @param M
	 *            常量，选择数据个数
	 * @param list
	 *            存放计算结果
	 */
	public static void combine(int a[], int n, int m, int b[], final int M, List<int[]> list) {
		for (int i = n; i >= m; i--) {
			b[m - 1] = i - 1;
			if (m > 1)
				combine(a, i - 1, m - 1, b, M, list);
			else {
				int[] result = new int[M];
				for (int j = M - 1; j >= 0; j--) {
					result[j] = a[b[j]];
				}
				list.add(result);
			}
		}
	}

	public static String getChuanResult(int m, int n) {
		StringBuffer result = new StringBuffer();
		switch (m){
			case 3:
				if(n == 3){
					result.append("2串1");
				}else if(n == 4){
					result.append("2串1,3串1");
				}
				break;
			case 4:
				if(n == 4){
					result.append("3串1");
				}else if(n == 5){
					result.append("3串1,4串1");
				}else if(n == 6){
					result.append("2串1");
				}else if(n == 11){
					result.append("2串1,3串1,4串1");
				}
				break;
			case 5:
				if(n == 5){
					result.append("4串1");
				}else if(n == 6){
					result.append("4串1,5串1");
				}else if(n == 10){
					result.append("2串1");
				}else if(n == 16){
					result.append("3串1,4串1,5串1");
				}else if(n == 20){
					result.append("2串1,3串1");
				}else if(n == 26){
					result.append("2串1,3串1,4串1,5串1");
				}
				break;
			case 6:
				if(n == 6){
					result.append("5串1");
				}else if(n == 7){
					result.append("5串1,6串1");
				}else if(n == 15){
					result.append("2串1");
				}else if(n == 20){
					result.append("3串1");
				}else if(n == 22){
					result.append("4串1,5串1,6串1");
				}else if(n == 35){
					result.append("2串1,3串1");
				}else if(n == 42){
					result.append("3串1,4串1,5串1,6串1");
				}else if(n == 50){
					result.append("2串1,3串1,4串1");
				}else if(n == 57){
					result.append("2串1,3串1,4串1,5串1,6串1");
				}
				break;
			case 7:
				if(n == 7){
					result.append("6串1");
				}else if(n == 8){
					result.append("6串1,7串1");
				}else if(n == 21){
					result.append("5串1");
				}else if(n == 35){
					result.append("4串1");
				}else if(n == 120){
					result.append("2串1,3串1,4串1,5串1,6串1,7串1");
				}
				break;
			case 8:
				if(n == 8){
					result.append("7串1");
				}else if(n == 9){
					result.append("7串1,8串1");
				}else if(n == 28){
					result.append("6串1");
				}else if(n == 56){
					result.append("5串1");
				}else if(n == 70){
					result.append("4串1");
				}else if(n == 247){
					result.append("2串1,3串1,4串1,5串1,6串1,7串1,8串1");
				}
				break;
		}
		return result.toString();
	}

	public static int caculateZhushu(String result, String betcode, int num, boolean isdanguan, List<Boolean> isDanList){
		int isDanNum = getIsDanNum(isDanList);
		int zhushu = 0;
		if(isDanNum>0){
			zhushu = caculateZhushuDTMix(result, betcode, num, isdanguan);
		}else{
			zhushu = caculateZhushuMix(result, betcode, num, isdanguan);
		}
		return zhushu;
	}

    /**
     * 计算注数
     * @param betcode
     * @param num
     * @return
     */
    public static int caculateZhushuMix(String result, String betcode, int num, boolean isdanguan) {
		List<String> chuans = JC_GuoGuanInfor.getChuanIds(result, isdanguan);
        betcode = betcode.replace("^", "");
        List<List<String>> convert = convert(betcode, num);
        List<List<String>> n1Codes = splitToN1(convert, Integer.parseInt(chuans.get(0)));

        int zhushu = 0;
        for(List<String> n1code:n1Codes) {
            zhushu = zhushu + mulSelectCode(n1code);
        }
        return zhushu;
    }

	/**
	 * 计算注数(胆拖混合)
	 * @param betcode
	 * @param num
	 * @return
	 */
	public static int caculateZhushuDTMix(String result, String betcode, int num, boolean isdanguan) {
		List<String> chuans = JC_GuoGuanInfor.getChuanIds(result, isdanguan);
		betcode = betcode.replace("^", "");
		List<List<String>> convert = convertDT(betcode, num);
		List<List<String>> n1Codes = splitToN1(convert, Integer.parseInt(chuans.get(0)));

		int zhushu = 0;
		for(List<String> n1code:n1Codes) {
			zhushu = zhushu + mulSelectCode(n1code);
		}
		return zhushu;
	}

	/**
	 * 将混合投注的注码转换为标准串关形式的注码(玩法不限制)胆拖
	 * @param betcode 注码
	 * @param num 串关数
	 * @return
	 */
	public static List<List<String>> convertDT(String betcode,int num) {
		int danlength = getDistinctMatches(betcode.split("\\#")[0]).size();
		Map<String, List<String>> splitByMatchdan = splitByMatch(betcode.split("\\#")[0]);
		Map<String, List<String>> splitByMatchtuo = splitByMatch(betcode.split("\\#")[1]);
		List<Map<String, List<String>>> splitMatchByNum = splitMatchByNum(splitByMatchtuo,num-danlength);

		for(Map<String, List<String>> map:splitMatchByNum) {
			map.putAll(splitByMatchdan);
		}
		List<List<String>> convertToStandardMatch = convertToStandardMatch(splitMatchByNum);
		return convertToStandardMatch;
	}

	public static Set<String> getDistinctMatches(String codes) {
		Set<String> matches = new HashSet<String>();

		for(String code:codes.split("\\|")) {
			matches.add(code.substring(0, 11));
		}
		return matches;
	}

    /**
     * 将混合投注的注码转换为标准串关形式的注码(玩法不限制)
     * @param betcode 注码
     * @param num 串关数
     * @return
     */
    public static List<List<String>> convert(String betcode, int num) {
        Map<String, List<String>> splitByMatch = splitByMatch(betcode);
        List<Map<String, List<String>>> splitMatchByNum = splitMatchByNum(splitByMatch,num);
        List<List<String>> convertToStandardMatch = convertToStandardMatch(splitMatchByNum);

        return convertToStandardMatch;
    }

    /**
     * 讲标准注码转换为串1形式来计算注数
     * @param codeCollection
     * @param type
     * @return
     */
    public static List<List<String>> splitToN1(List<List<String>> codeCollection, int type) {
        List<List<String>> allcodes = new ArrayList<List<String>>();
        List<Integer> combinations = getCombinationsByType(type);
        for(int i:combinations) {
            allcodes.addAll(combinationList(codeCollection, i));
        }
        return allcodes;
    }

    /**
     * 循环计算每个串1的注数
     * @param betcodes
     * @param c
     * @return
     */
    public static List<List<String>> combinationList(List<List<String>> betcodes,int c) {
        List<List<String>> list = new ArrayList<List<String>>();
        for(List<String> betcode:betcodes) {
            list.addAll(getCodeCollection(betcode, c));
        }
        return list;
    }

    public static int mulSelectCode(List<String> selects) {
        int zhushu = 1;
        for(String select:selects) {
            int start = select.indexOf("(");
            int end = select.indexOf(")");
            select = select.substring(start+1, end);
            zhushu = zhushu * select.split(",").length;
        }
        return zhushu;
    }

    /**
     * 讲注码拆分为场次和所选内容的组合，map的key为场次，value为投注内容
     * @param betcode
     * @return
     */
    public static Map<String,List<String>> splitByMatch(String betcode) {
        Map<String,List<String>> map = new HashMap<String,List<String>>();
        for(String code:betcode.split("\\|")) {
            if(map.get(code.substring(0, 11))==null) {
                List<String> list = new ArrayList<String>();
                list.add(code);
                map.put(code.substring(0, 11), list);
            }else {
                List<String> list = map.get(code.substring(0, 11));
                list.add(code);
                map.put(code.substring(0, 11), list);
            }
        }
        return map;
    }

    /**
     * 按照num数组合场次
     * @param matchs key为场次 value为内容
     * @param num
     * @return
     */
    public static List<Map<String,List<String>>> splitMatchByNum(Map<String,List<String>> matchs,int num) {
        Set<String> keyset = matchs.keySet();
        List<String> list = new ArrayList<String>();

        for (Iterator<String> iterator = keyset.iterator(); iterator.hasNext();) {
			String string = iterator.next();
			list.add(string);
		}

        List<List<String>> split = getCodeCollection(list, num);

        List<Map<String,List<String>>> listmap = new ArrayList<Map<String,List<String>>>();
        for(List<String> strings:split) {
            Map<String,List<String>> map = new HashMap<String,List<String>>();
            for(String match:strings) {
                map.put(match, matchs.get(match));
            }
            listmap.add(map);
        }

        return listmap;
    }

    /**
     * 输出全部组合数
     * @param betcodes  被选择的数据
     * @param select  选择的个数
     * @return
     */
    public static List<List<String>> getCodeCollection(List<String> betcodes,
                                                       int select) {
        // 初始化原始数据
        int[] a = new int[betcodes.size()];
        for (int i = 0; i < a.length; i++) {
            a[i] = i;
        }
        // 接收数据
        int[] b = new int[select];

        List<int[]> list = new ArrayList<int[]>();

        // 进行组合
        combine(a, a.length, select, b, select, list);

        // 返回数据对象
        List<List<String>> reList = new ArrayList<List<String>>();
        for (int[] result : list) {
            List<String> codeList = new ArrayList<String>();
            for (int p : result) {
                codeList.add(betcodes.get(p));
            }
            reList.add(codeList);
        }

        return reList;
    }

    /**
     * 根据map的大小将注码转换为以map.size为长度的标砖串关注码(玩法不限制)
     * @param matchs
     * @return
     */
    public static List<List<String>> convertToStandardMatch(List<Map<String,List<String>>> matchs) {
        List<List<String>> listMatchs = new ArrayList<List<String>>();
        for(Map<String,List<String>> map:matchs) {
            List<List<String>> listlist = new ArrayList<List<String>>();
            for (Iterator<String> iterator = map.keySet().iterator(); iterator.hasNext();) {
                String changci = iterator.next();
                List<String> changcicode = map.get(changci);
                listlist = rezuheList(listlist,changcicode);
            }
            listMatchs.addAll(listlist);
        }

        return listMatchs;
    }

    /**
     * 自上而下的组合方式如a,bc,d，组合为abd，acd
     * @param listlistOri 原始组合列
     * @param as 新添加组合列
     * @return
     */
    public static List<List<String>> rezuheList(List<List<String>> listlistOri,List<String> as) {
        List<List<String>> listlist = new ArrayList<List<String>>();
        if(listlistOri.size()==0) {
            for(String a:as) {
                List<String> list = new ArrayList<String>();
                list.add(a);
                listlist.add(list);
            }
            return listlist;
        }

        for(List<String> list:listlistOri) {
            for(String a:as) {
                ArrayList<String> newlist = new ArrayList<String>();
                newlist.addAll(list);
                newlist.add(a);
                listlist.add(newlist);
            }
        }
        return listlist;
    }

    public static List<Integer> getCombinationsByType(int type) {
        List<Integer> combinations = new ArrayList<Integer>();

        switch(type) {
            case 1001:
                combinations.add(1);
                break;
            case 2001:
                combinations.add(2);
                break;
            case 3001:
                combinations.add(3);
                break;
            case 3003:
                combinations.add(2);
                break;
            case 3004:
                combinations.add(2);
                combinations.add(3);
                break;
            case 4001:
                combinations.add(4);
                break;
            case 4004:
                combinations.add(3);
                break;
            case 4005:
                combinations.add(3);
                combinations.add(4);
                break;
            case 4006:
                combinations.add(2);
                break;
            case 4011:
                combinations.add(2);
                combinations.add(3);
                combinations.add(4);
                break;
            case 5001:
                combinations.add(5);
                break;
            case 5005:
                combinations.add(4);
                break;
            case 5006:
                combinations.add(4);
                combinations.add(5);
                break;
            case 5010:
                combinations.add(2);
                break;
            case 5016:
                combinations.add(3);
                combinations.add(4);
                combinations.add(5);
                break;
            case 5020:
                combinations.add(2);
                combinations.add(3);
                break;
            case 5026:
                combinations.add(2);
                combinations.add(3);
                combinations.add(4);
                combinations.add(5);
                break;
            case 6001:
                combinations.add(6);
                break;
            case 6006:
                combinations.add(5);
                break;
            case 6007:
                combinations.add(5);
                combinations.add(6);
                break;
            case 6015:
                combinations.add(2);
                break;
            case 6020:
                combinations.add(3);
                break;
            case 6022:
                combinations.add(4);
                combinations.add(5);
                combinations.add(6);
                break;
            case 6035:
                combinations.add(2);
                combinations.add(3);
                break;
            case 6042:
                combinations.add(3);
                combinations.add(4);
                combinations.add(5);
                combinations.add(6);
                break;
            case 6050:
                combinations.add(2);
                combinations.add(3);
                combinations.add(4);
                break;
            case 6057:
                combinations.add(2);
                combinations.add(3);
                combinations.add(4);
                combinations.add(5);
                combinations.add(6);
                break;
            case 7001:
                combinations.add(7);
                break;
            case 7007:
                combinations.add(6);
                break;
            case 7008:
                combinations.add(6);
                combinations.add(7);
                break;
            case 7021:
                combinations.add(5);
                break;
            case 7035:
                combinations.add(4);
                break;
            case 7120:
                combinations.add(2);
                combinations.add(3);
                combinations.add(4);
                combinations.add(5);
                combinations.add(6);
                combinations.add(7);
                break;
            case 8001:
                combinations.add(8);
                break;
            case 8008:
                combinations.add(7);
                break;
            case 8009:
                combinations.add(7);
                combinations.add(8);
                break;
            case 8028:
                combinations.add(6);
                break;
            case 8056:
                combinations.add(5);
                break;
            case 8070:
                combinations.add(4);
                break;
            case 8247:
                combinations.add(2);
                combinations.add(3);
                combinations.add(4);
                combinations.add(5);
                combinations.add(6);
                combinations.add(7);
                combinations.add(8);
                break;
            case 2003:
                combinations.add(1);
                combinations.add(2);
                break;
            case 3006:
                combinations.add(1);
                combinations.add(2);
                break;
            case 3007:
                combinations.add(1);
                combinations.add(2);
                combinations.add(3);
                break;
            case 4010:
                combinations.add(1);
                combinations.add(2);
                break;
            case 4014:
                combinations.add(1);
                combinations.add(2);
                combinations.add(3);
                break;
            case 4015:
                combinations.add(1);
                combinations.add(2);
                combinations.add(3);
                combinations.add(4);
                break;
            case 5015:
                combinations.add(1);
                combinations.add(2);
                break;
            case 5025:
                combinations.add(1);
                combinations.add(2);
                combinations.add(3);
                break;
            case 5030:
                combinations.add(1);
                combinations.add(2);
                combinations.add(3);
                combinations.add(4);
                break;
            case 5031:
                combinations.add(1);
                combinations.add(2);
                combinations.add(3);
                combinations.add(4);
                combinations.add(5);
                break;
            case 6021:
                combinations.add(1);
                combinations.add(2);
                break;
            case 6041:
                combinations.add(1);
                combinations.add(2);
                combinations.add(3);
                break;
            case 6056:
                combinations.add(1);
                combinations.add(2);
                combinations.add(3);
                combinations.add(4);
                break;
            case 6062:
                combinations.add(1);
                combinations.add(2);
                combinations.add(3);
                combinations.add(4);
                combinations.add(5);
                break;
            case 6063:
                combinations.add(1);
                combinations.add(2);
                combinations.add(3);
                combinations.add(4);
                combinations.add(5);
                combinations.add(6);
                break;
            case 7127:
                combinations.add(1);
                combinations.add(2);
                combinations.add(3);
                combinations.add(4);
                combinations.add(5);
                combinations.add(6);
                combinations.add(7);
                break;
            case 8255:
                combinations.add(1);
                combinations.add(2);
                combinations.add(3);
                combinations.add(4);
                combinations.add(5);
                combinations.add(6);
                combinations.add(7);
                combinations.add(8);
                break;
        }

        return combinations;
    }

}
